%{
package pkg.nudroid.translator;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
%}

/* YACC Declarations 
%token <sval> IDENTIFIER
%token <sval> NAME
%token <dval> NUMBER
%token <sval> STRING
%token <sval> UNFORMATTED_STRING
*/

/* YACC Declarations */
%token IDENTIFIER
%token NAME
%token NUMBER
%token STRING
%token UNFORMATTED_STRING

/* Tag Tokens: Opening tag: T_X = "<X".
   Closing tag:  CT_X = "</X>" */
%token T_NUDROID
%token CT_NUDROID
%token T_NAVIGATION
%token CT_NAVIGATION
%token T_STYLE
%token CT_STYLE
%token T_PAGE
%token CT_PAGE
%token T_TEXT
%token CT_TEXT
%token T_INPUT
%token CT_INPUT
%token T_LINK
%token CT_LINK
%token T_IMAGE
%token CT_IMAGE
%token T_LIST
%token CT_LIST
%token T_TABLE
%token CT_TABLE
%token T_AUDIO
%token CT_AUDIO
%token T_VIDEO
%token CT_VIDEO
%token T_BUTTON
%token CT_BUTTON
%token T_FUNCTION
%token CT_FUNCTION
%token T_VAR
%token CT_VAR
%token T_GOTO
%token T_SETVAR
%token T_GETVAR
%token T_GETINPUT
%token T_GETTEXT
%token T_SETTEXT
%token T_LOOP
%token CT_LOOP
%token T_TEST
%token CT_TEST
%token T_TRUE
%token CT_TRUE
%token T_FALSE
%token CT_FALSE
%token CT_SELF_CLOSING
%token CT_SETTEXT
%token T_MENU
%token CT_MENU

//Boolean literals
%token B_TRUE
%token B_FALSE

//Parameters
%token P_NAME
%token P_PAGEID
%token P_URL
%token P_EMAIL
%token P_BULLET_STYLE
%token P_TYPE
%token P_COLS
%token P_FUNCTIONID
%token P_TYPE
%token P_VALUE
%token P_CONDITION
%token P_START
%token P_END
%token P_ID
%token P_LABEL
%token P_STYLEID
%token P_POSITION
%token P_HEIGHT
%token P_WIDTH
%token P_LOCATION
%token P_SIZE
%token P_COLOR
%token P_FONT
%token P_LORIENTATION

%token P_VARID
%token P_TEXTID
%token P_INPUTID
%token P_TEXT

//Miscellaneous String Tokens
%token FONT_SERIF 			//"serif"
%token FONT_SANS  			//"sans"
%token FONT_MONO			//"mono"
%token BULLET_NUMBERS		//"numbers"
%token BULLET_ATOZ_UPPER	//"AtoZ"
%token BULLET_ATOZ_LOWER	//"atoz"
%token BULLET_CIRCLES		//"circles"
%token BULLET_SQUARES		//"squares"
%token BULLET_DISCS			//"discs"
%token LIST_VERTICAL		//"vertical"
%token LIST_HORIZONTAL		//"horizontal"
%token TYPE_NUMBER			//"number"
%token TYPE_STRING			//"string"
%token LOGIC_OR				//"||"
%token LOGIC_AND			//"&&"
%token RELOP_EQ				//"=="
%token RELOP_NEQ			//"!="
%token RELOP_GEQ			//">="
%token RELOP_LEQ			//"<="
%token POSITION_TOP			//"top"
%token POSITION_BOTTOM		//"bottom"
%token POSITION_LEFT		//"left"
%token POSITION_RIGHT		//"right"
%token POSITION_CENTER		//"center"
%token ORIENTATION_VERTICAL	//"vertical"
%token ORIENTATION_HORIZONTAL //"horizontal




/* Condition operator associativity */
%left LOGIC_OR
%left LOGIC_AND
%left "!"

/* Grammar follows */
%%

/* APP */

app: T_NUDROID app_name ">" navigation body CT_NUDROID 
{

	// To initialize variables
	try
	{
		String initFile = "package pkg.nudroid;\n" +

		"public class Init\n"+
		"{\n" + 
		"\tstatic void init()\n" +
		"\t{\n" +
		variableDeclarations +
		"\t}\n" +
		"}";
		
		String path = System.getProperty("user.dir")  + "/src/pkg/nudroid/" + "Init" + ".java";
		FileWriter fw = new FileWriter(path);
		fw.write(initFile);
		fw.close();
		System.out.println("Successed");
	}
	catch(Exception e)
	{
		e.printStackTrace();
	}

	// To make folder
	try
	{			
		/*
		// make directory hierarchy
		File f1, f2, f3, f4, f5, f6, f7, f8;
		
	    f1 = new File($2.sval + "/gen");
	    f2 = new File($2.sval + "/assets");
	    f3 = new File($2.sval + "/src/pkg/nudroid");
	    if (!f1.mkdirs() || !f2.mkdirs() || !f3.mkdirs())
	      System.err.println("fail to create directory");
		
	    // make sub-directory 
	    f4 = new File($2.sval + "/res/drawable-hdpi");
	    f5 = new File($2.sval + "/res/drawable-ldpi");
	    f6 = new File($2.sval + "/res/drawable-mdpi");
	    f7 = new File($2.sval + "/res/layout");
	    f8 = new File($2.sval + "/res/values");
	    if (!f4.mkdirs() || !f5.mkdirs() || !f6.mkdirs() || !f7.mkdirs() || !f8.mkdirs())
	      System.err.println("fail to create directory");	 
	    */
	      
    	BufferedWriter out1, out2, out3, out4;
    	String s1, s2, s3, s4;
    	
    	// first file
		  out1 = new BufferedWriter(new FileWriter(System.getProperty("user.dir") + "/src/pkg/nudroid/AndroidManifest.xml"));
		  
		  s1 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";		
		  out1.write(s1); out1.newLine();
		  s1 = "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"";
		  out1.write(s1); out1.newLine();	
		  s1 = "\tpackage=\"pkg.nudroid\"";
		  out1.write(s1); out1.newLine();	
		  s1 = "\tandroid:versionCode=\"1\"";
		  out1.write(s1); out1.newLine();
		  s1 = "\tandroid:versionName=\"1.0\">";
		  out1.write(s1); out1.newLine();
		  s1 = "\t\t\t\t<uses-permission android:name=\"android.permission.INTERNET\" />";
		  out1.write(s1); out1.newLine();	
		  s1 = "\t<application android:icon=\"@drawable/icon\" android:label=\"" + $2.sval + "\">";
		  out1.write(s1); out1.newLine();
		  
		  s1 = "\t\t<activity android:name=\"." + pageIDs.get(0) + "\"";		
		  out1.write(s1); out1.newLine();
		  s1 = "\t\t\tandroid:label=\"" + pageIDs.get(0) + "\">";
		  out1.write(s1); out1.newLine();		  
		  s1 = "\t\t\t\t<intent-filter>";
		  out1.write(s1); out1.newLine();
		  s1 = "\t\t\t\t\t<action android:name=\"android.intent.action.MAIN\" />";
		  out1.write(s1); out1.newLine();
		  s1 = "\t\t\t\t\t<category android:name=\"android.intent.category.LAUNCHER\" />";
		  out1.write(s1); out1.newLine();
		  s1 = "\t\t\t\t</intent-filter>";
		  out1.write(s1); out1.newLine();
		  s1 = "\t\t</activity>	";
		  out1.write(s1); out1.newLine();
		  
		  // It should make all page activity
		 for(int i = 1; i < pageIDs.size(); i ++)
		{
			s1 = "\t\t<activity android:name=\"." + pageIDs.get(i) + "\"";		
			out1.write(s1); out1.newLine();
			s1 = "\t\t\tandroid:label=\"" + pageIDs.get(i) + "\">";
		  	out1.write(s1); out1.newLine();
		  	s1 = "\t\t</activity>	";
		  	out1.write(s1); out1.newLine();
		  
		};
		  		  	  
		  s1 = "\t</application>";
		  out1.write(s1); out1.newLine();
		  s1 = "\t<uses-sdk android:minSdkVersion=\"7\" />";
		  out1.write(s1); out1.newLine();
		  s1 = "</manifest> ";
		  out1.write(s1); out1.newLine();
		  out1.close();      
		
		  // second file
		
		  out2 = new BufferedWriter(new FileWriter(System.getProperty("user.dir") + "/src/pkg/nudroid/default.properties"));

		  s2 = "# Indicates whether an apk should be generated for each density.";
		  out2.write(s2); out2.newLine();
		  s2 = "split.density=false";		
		  out2.write(s2); out2.newLine();
		  s2 = "# Project target.";
		  out2.write(s2); out2.newLine();	
		  s2 = "target=android-7";
		  out2.write(s2); out2.newLine();	
		  out2.close();
		  
		  // third file
		  out3 = new BufferedWriter(new FileWriter(System.getProperty("user.dir") + "/src/pkg/nudroid/row.xml"));
		  s3 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
		  out3.write(s3); out3.newLine();
		  s3 = "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"";		
		  out3.write(s3); out3.newLine();
		  s3 = "android:layout_width=\"fill_parent\" android:layout_height=\"wrap_content\"";
		  out3.write(s3); out3.newLine();	
		  s3 = "android:orientation=\"horizontal\">";
		  out3.write(s3); out3.newLine();	
		  s3 = "<TableRow android:id=\"@+id/TableRow\" android:layout_width=\"wrap_content\"";
		  out3.write(s3); out3.newLine();
		  s3 = "android:layout_height=\"wrap_content\">";
		  out3.write(s3); out3.newLine();
		  s3 = "<ImageView ";
		  out3.write(s3); out3.newLine();
		  s3 = "android:id=\"@+id/bulletpoint\"";
		  out3.write(s3); out3.newLine();
		  s3 = "android:paddingLeft=\"0px\" android:paddingRight=\"0px\"";
		  out3.write(s3); out3.newLine();
		  s3 = "android:paddingTop=\"0px\" android:layout_height=\"wrap_content\"/>";
		  out3.write(s3); out3.newLine();
		  s3 = "<TextView ";
		  out3.write(s3); out3.newLine();
		  s3 = "android:id=\"@+id/text\"";
		  out3.write(s3); out3.newLine();
		  s3 = "android:text=\"\"";
		  out3.write(s3); out3.newLine();
		  s3 = "android:layout_width=\"wrap_content\"";
		  out3.write(s3); out3.newLine();
		  s3 = "android:layout_height=\"24sp\"";
		  out3.write(s3); out3.newLine();
		  s3 = "android:textSize=\"16sp\" />";
		  out3.write(s3); out3.newLine();
		  s3 = "</TableRow>";
		  out3.write(s3); out3.newLine();
		  s3 = "</LinearLayout>";
		  out3.write(s3); out3.newLine();
		  out3.close();	
	
		  s4 =
		  	"\tpackage pkg.nudroid;\n" + 
		  	"\timport java.util.HashMap;\n" +
			"\timport java.util.HashSet;\n" +
			"\tpublic class SymbolTable \n" +
			"\t{\n" +
				"\tprivate static HashMap<String,STValue> symbolTable;\n" +
				"\tprivate static HashSet<String> initializedVariables;\n" +
				"\tprivate static HashSet<String> initializedInputs;\n" +
				"\tprivate static int temp;\n\n" +
	
			"\tpublic static enum Type\n" +
			"\t{\n" +
				"\tAPP,\n" +
				"\tPAGE,\n" +
				"\tTEXT,\n" +
				"\tINPUT,\n" +
				"\tLINK,\n" +
				"\tIMAGE,\n" +
				"\tLIST,\n" +
				"\tTABLE,\n" +
				"\tAUDIO,\n" +
				"\tVIDEO,\n" +
				"\tBUTTON,\n" +
				"\tFUNCTION,\n" +
				"\tVARIABLE\n" +
			"\t}\n\n" +
	
			"\tpublic static class STValue\n" +
			"\t{\n" +
				"\tType type;\n" +
				"\tint value;\n" +
				
				"\tpublic STValue(Type t)\n" +
				"\t{\n" +
					"\ttype = t;\n" +
				"\t}\n\n" +
				
				"\tpublic STValue(int d)\n" +
				"\t{\n" +
					"\ttype = Type.VARIABLE;\n" +
					"\tvalue = d;\n" +
				"\t}\n\n" +
				
				"\tpublic double getValue()\n" +
				"\t{\n" +
					"\tif(type == Type.VARIABLE)\n" +
						"\treturn value;\n" +
					"\telse if(type == Type.INPUT)\n" +
					"\t{\n" +
						"\tthrow new IllegalArgumentException(\"Input objects not yet supported.\");\n" +
					"\t}\n" +
					"\telse\n" +
					"\t{\n" +
						"\tthrow new IllegalArgumentException(\"Not a variable name.\");\n" +
					"\t}\n\n" +
					
				"\t}\n" +
			"\t}\n\n" +
			
			"\tstatic\n" +
			"\t{\n" +
				"\tinitialize();\n" +
			"\t}\n\n" +
			
			"\tpublic static void initialize()\n" +
			"\t{\n" +
				"\tsymbolTable = new HashMap<String, STValue>();\n" +
				"\tinitializedVariables = new HashSet<String>();\n" +
				"\tinitializedInputs = new HashSet<String>();\n" +
				"\ttemp = 0;\n" +
				"\tInit.init();\n" +
			"\t}\n\n" +
			
			"\tpublic static String tempVarName()\n" +
			"\t{\n" +
				"\tString name = \"temporaryVariableName\" + temp;\n" +
				"\ttemp++;\n" +
				"\treturn name;\n" +
			"\t}\n" +
			
			"\tpublic static boolean addSymbol(String id, Type t)\n" +
			"\t{\n" +
				"\tif (symbolTable.containsKey(id))\n" +
					"\treturn false;\n" +
					
				"\tsymbolTable.put(id,new STValue(t));\n" +
				"\treturn true;\n" +
			"\t}\n" +
			
			"\tpublic static boolean addVar(String id, int d)\n" +
			"\t{\n" +
				"\tif(symbolTable.containsKey(id))\n" +
					"\treturn false;\n\n" +
				
				"\tsymbolTable.put(id, new STValue(d));\n" +
				"\treturn true;\n" +
			"\t}\n\n" +
		
			"\tpublic static boolean contains(String id)\n" +
			"\t{\n" +
				"\treturn symbolTable.containsKey(id);\n" +
			"\t}\n\n" +
		
			"\tpublic static Type typeOfID(String id)\n" +
			"\t{\n" +
				"\treturn symbolTable.get(id).type;\n" +
			"\t}\n\n" +
			
			"\tpublic static int getVar(String id)\n" +
			"\t{\n" +
				"\treturn symbolTable.get(id).value;\n" +
			"\t}\n\n" +
			
			"\tpublic static void setVar(String id, int d)\n" +
			"\t{\n" +
				"\tsymbolTable.get(id).value = d;\n" +
			"\t}\n\n" +
			
			"\tpublic static boolean containsVariable(String id)\n" +
			"\t{\n" +
				"\treturn initializedVariables.contains(id);\n" +
			"\t}\n\n" +
			
			"\tpublic static void initializeVariable(String id)\n" +
			"\t{\n" +
				"\tif(containsInput(id))\n" +
					"\tSystem.err.println(id + \" has already been declared as an input.\");\n\n" +
				
				"\tinitializedVariables.add(id);\n" +
			"\t}\n\n" +
			
			"\tpublic static void clearInputs()\n" +
			"\t{\n" +
				"\tinitializedInputs = new HashSet<String>();\n" +
			"\t}\n\n" +
			
			"\tpublic static boolean containsInput(String id)\n" +
			"\t{\n" +
				"\treturn initializedInputs.contains(id);\n" +
			"\t}\n\n" +
			
			"\tpublic static void initializeInput(String id)\n" +
			"\t{\n" +
				"\tif(containsVariable(id))\n" +
				"\t{\n" +
					"\tSystem.err.println(id + \" has already been declared as a variable.\");\n" +
					"\treturn;\n" +
				"\t}\n" +
				"\tinitializedInputs.add(id);\n" +
			"\t}\n\n" +

		  "\tstatic int safeParseInt(String s)\n" +
		  "\t{\n" +
		  	"\ttry\n" +
		  	"\t{\n" +
		  		"\tint i = Integer.parseInt(s);\n" +
		  		"\treturn i;\n" +
		  	"\t}\n" +
		  	"\tcatch(NumberFormatException e)\n" +
		  	"\t{\n" +
		  		"\treturn 0;\n" +
		  	"\t}\n" +
		  "\t}\n" +
		"\t}\n";
	
	out4 = new BufferedWriter(new FileWriter(System.getProperty("user.dir") + "/src/pkg/nudroid/SymbolTable.java"));
	out4.write(s4);
	out4.close();
			  		  
	}
	catch (Exception e)
	{
		System.out.println("Err: Make folder - " + e);
	}
}
   //| error CT_NUDROID {System.err.println("Malformed <NuDroid> tag.");}
;

body: /* Empty String*/ {$$.sval = "";}
   | body upper_level_tag {$$.sval = $1.sval + $2.sval;}
   ;

upper_level_tag: page 	{$$.sval = $1.sval;}
   | variable			{$$.sval = $1.sval;}
;

app_name: P_NAME IDENTIFIER {$$.sval = $2.sval;}
;

/* NAVIGATION */
navigation: /* Empty */ {;}
| T_NAVIGATION ">" tabs CT_NAVIGATION
{ 	
	$$.sval = 
	"\n\t//Navigation\n" +
	"\t@Override\n" +
	"\tpublic boolean onCreateOptionsMenu(Menu menu)\n" +
	"\t{\n" +
	"\t\tsuper.onCreateOptionsMenu(menu);\n";
			
	for(int i = 0; i < pageTitles.size(); i ++)
	{		
		$$.sval = $$.sval + "\t\tmenu.add(0," + i + "," + i +"," + pageTitles.get(i) + ");\n";
	};
	
	$$.sval = $$.sval +
	    "\t\treturn true;\n" +
	"\t}\n" +
	
	"\n\t@Override\n" +
	"\tpublic boolean onOptionsItemSelected(MenuItem item)\n" +
	"\t{\n" +
	"\t\tsuper.onOptionsItemSelected(item);	\n" +
		"\t\tswitch (item.getItemId())\n" +
		"\t\t{\n";
		
	for(int i = 0; i < pageTitles.size(); i ++)
	{
		$$.sval = $$.sval +  
		"\t\tcase " + i + ":\n" +
		"\t\t startActivity(new Intent(this," + pageIDs.get(i) + ".class));\n" +
		"\t\treturn true;\n";
	};	
	
	$$.sval = $$.sval +	
	"\t\t}\n" +
	"\t\treturn super.onOptionsItemSelected(item);\n" +
	"\t}\n";
		
	navigationTemp = $$.sval;
}
;

tabs: /* Empty String */ {$$.sval = "";}
   | tabs tab 
;

tab: menu {$$.sval = $1.sval;}
;

/* MENU */

menu: T_MENU id page_id ">" unformatted_string CT_MENU
{
	pageIDs.add($3.sval);
	pageTitles.add($5.sval);
}
;

/* PAGE */

page: T_PAGE id page_params ">" page_body CT_PAGE
{
	if($2.sval != "" && !pageIDs.contains($2.sval))
	{
		System.out.println("Page: " + $2.sval);
		pageIDs.add($2.sval);
		if($3.sval != "")
			pageTitles.add($3.sval); //for now, since label is only param
		else
			pageTitles.add($2.sval);
	}
	
	$$.sval = 
	
	"package pkg.nudroid;\n\n" +
	"import android.view.LayoutInflater;\n" + 
	"import android.net.Uri;\n" +
	"import android.widget.AdapterView.OnItemClickListener;\n" +
	"import android.app.Activity;\n" +
	"import java.util.ArrayList;\n" +
	"import android.view.Menu;\n" +
	"import android.view.MenuItem;\n" +	
	"import android.view.View;\n" +	
	"import android.view.ViewGroup;\n" + 
	"import android.os.Bundle;\n" +
	"import android.widget.*;\n" +
	"import android.content.Intent;\n" +
	"import android.view.ViewGroup.LayoutParams;\n" +
	"import android.graphics.*;\n" +
	"import java.net.*;\n" +
	"import java.io.InputStream;\n" +
	"import android.text.util.Linkify;\n" +
	"import android.media.MediaPlayer;\n" +
	"import java.io.BufferedInputStream;\n\n" +
			
	"public class " + $2.sval + " extends Activity\n" + 
	"{\n" +
		"\t// Default layout\n" +
	    "\tRelativeLayout nudroidLayout;\n" +
	    "\tIntent intent;\n" +
	    "\tint autoID = 1;\n" +
	    "\tprivate ArrayList<String> listTitleData = new ArrayList<String>();\n" +
		"\tArrayList<ListData> items = new ArrayList<ListData>();\n\n" +
	
		"\tpublic class ListData\n" + 
		"\t{\n" +
			"\t\tpublic String text = \"\";\n" + 
			"\t\tpublic int bulletpoint;\n" +
		"\t}\n\n" +
	
		"\t@Override\n"+
		"\tpublic void onCreate(Bundle savedInstanceState)\n"+ 
		"\t{\n"+
		"\t\tsuper.onCreate(savedInstanceState);\n"+
        "\n\t\t// To create default layout\n"+
        "\t\tnudroidLayout = new RelativeLayout(this);\n"+
        "\t\tfinal Activity thisPage = this;\n" +
                        
        "\n\t\t// To create page text\n" +
        "\t\tTextView " + $2.sval + "= new TextView(this);\n" +
        "\t\t" + $2.sval + ".setText(\"" + $3.sval + "\");\n" +
        "\t\t" + $2.sval + ".setId(autoID++);\n" +
                
		"\n\t\t// To define layout param\n" +
		"\t\tRelativeLayout.LayoutParams lpPage = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n"+
        "\t\tlpPage.addRule(RelativeLayout.CENTER_HORIZONTAL);\n" +
        "\t\t" + $2.sval + ".setLayoutParams(lpPage);\n\n" +
        
        "\t\tnudroidLayout.addView(" + $2.sval + ");\n" +
        
        "\t\t// To create dummy text\n" +
		"\t\tTextView dummy = new TextView(this);\n" +
		"\t\tdummy.setText(\" \");\n" +
		"\t\tdummy.setId(autoID++);\n" +
		
		"\t\t// To define layout param\n" +
		"\t\tRelativeLayout.LayoutParams lpPagedummy = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n" +
		"\t\tlpPagedummy.addRule(RelativeLayout.BELOW, autoID-2);\n" +
		"\t\tdummy.setLayoutParams(lpPagedummy);\n" +
		"\t\tnudroidLayout.addView(dummy);\n" +
        
        $5.sval + 
        
        "\n\t\t// To show views\n"+
        "\t\tsetContentView(nudroidLayout);\n"+
        
        tableLayout +
        
		"\t}\n" +
				
		navigationTemp +
		
		"\tclass IconicAdapter extends ArrayAdapter<ListData>\n" + 
		"\t{\n" + 
		"\t\tprivate LayoutInflater mInflater;\n" + 
		"\t\tActivity context;\n\n" + 
		"\t\tIconicAdapter(Activity context)\n" + 
		"\t\t{\n" + 
			"\t\t\tsuper(context, R.layout.row, items);\n" + 
			"\t\t\tmInflater = LayoutInflater.from(context);\n" + 
			"\t\t\tthis.context = context;\n" + 
		"\t\t}\n\n" + 

		"\t\tclass ViewHolder\n\n" + 
		"\t\t{\n" + 
			"\t\t\tTextView text;\n" + 
			"\t\t\tImageView icon;\n" + 
		"\t\t}\n\n" + 

		"\t\tpublic View getView(int position, View convertView, ViewGroup parent)\n" + 
		"\t\t{\n" + 
			"\t\t\tViewHolder holder;\n" + 
			"\t\t\tif (convertView == null)\n" + 
			"\t\t\t{\n" + 
				"\t\t\t\tconvertView = mInflater.inflate(R.layout.row, null);\n" + 
				"\t\t\t\tholder = new ViewHolder();\n" + 
				"\t\t\t\tholder.text = (TextView) convertView.findViewById(R.id.text);\n" + 
				"\t\t\t\tholder.icon = (ImageView) convertView.findViewById(R.id.bulletpoint);\n" + 
				"\t\t\t\tconvertView.setTag(holder);\n" + 
			"\t\t\t}\n" + 
			"\t\t\telse\n" + 
			"\t\t\t{\n" + 
				"\t\t\t\tholder = (ViewHolder) convertView.getTag();\n" + 
			"\t\t\t}\n" + 
			"\t\t\tholder.text.setText(items.get(position).text);\n" + 
			"\t\t\tholder.icon.setImageResource(items.get(position).bulletpoint);\n" +
			"\t\t\tLinkify.addLinks(holder.text, Linkify.WEB_URLS );\n" +			 
			"\t\t\treturn convertView;\n" +
		"\t\t}\n" + 
	"\t}\n" + 
      
      "}\n";
	
	// To save file
	try
	{
		//TODO - Giving compilation errors.
		File dirs = new File($2.sval);
		
		String path = System.getProperty("user.dir") + "/src/pkg/nudroid/" + $2.sval + ".java";
		FileWriter fw = new FileWriter(path);
		fw.write($$.sval);
		fw.close();
		System.out.println("Successed");
	}
	catch (IOException e)
	{
		e.getMessage();
		System.out.println("File open error: " + e);
	}
        layoutParams++; //Increments counter to ensure unique variable names for next run.
}
   // | error CT_PAGE {System.err.println("Malformed <Page> tag.");}
;

page_body: /* Empty String */ {$$.sval = "";}
   | page_body body_element {$$.sval=$1.sval+$2.sval;}
;

body_element: text 	{$$.sval = $1.sval;}
   | input {$$.sval = $1.sval;}
   | image {$$.sval = $1.sval;}
   | list {$$.sval = $1.sval;}
   | table {$$.sval = $1.sval;}
   | button {$$.sval = $1.sval;}
   | action {$$.sval = $1.sval;}
   //| function {$$.sval = $1.sval;}
   | audio {$$.sval = $1.sval;}
   | video {$$.sval = $1.sval;}
   | link 
   {
   	$$.sval = $1.sval;
   	listIDs.remove(listIDs.size()-1);
   	listTitle.remove(listTitle.size()-1);
   	listUrl.remove(listUrl.size()-1);
   }
;

page_params: /* Empty String */ {$$.sval = "";}
   | page_params page_param  { $$.sval = $1.sval + $2.sval;}
;

page_param: label { $$.sval = $1.sval; }
;

/* TEXT OBJECT */

text: T_TEXT id ">" formatted_string CT_TEXT
{
	$$.sval = "\n\t\t// To create text\n" +
	"\t\tfinal TextView " + $2.sval + " = new TextView(this);\n" +
	"\t\t" + $2.sval + ".setText(" + $4.sval + ");\n" +
	"\t\t" + $2.sval + ".setId(autoID++);\n" +
	
	"\n\t\t// To define layout param\n" +
	"\t\tRelativeLayout.LayoutParams lpText" + $2.sval + " = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n"+
    "\t\tlpText" + $2.sval + ".addRule(RelativeLayout.BELOW, autoID-2);\n" +
    "\t\t" + $2.sval + ".setLayoutParams(lpText" + $2.sval + ");\n\n" +
    "\t\tnudroidLayout.addView(" + $2.sval + ");\n"
	;
}
//| error CT_TEXT {System.err.println("Malformed <TEXT> tag.");}
;

/* INPUT OBJECT */
input: T_INPUT id ">" unformatted_string CT_INPUT
{
	SymbolTable.initializeInput($2.sval);
	
	$$.sval = 
	"\n\t\t//Input Start;\n" +
	
	"\t\tRelativeLayout.LayoutParams lp" + $2.sval + " = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n" +
	"\t\tlp" + $2.sval + ".addRule(RelativeLayout.BELOW, autoID-2);\n" +
	
	"\t\tfinal EditText " + $2.sval + " = new EditText(this);\n" +
	"\t\t" + $2.sval + ".setText(" + $4.sval + ");\n" +
	"\t\t" + $2.sval + ".setId(autoID++);\n" +
	"\t\t" + $2.sval + ".setLayoutParams(lp" + $2.sval + ");\n" +
	"\t\tnudroidLayout.addView(" + $2.sval + ");\n" +
	"\t\t//Input End;\n"
;}
//| error CT_INPUT {System.err.println("Malformed <input> tag.");}
;

/* LINK */
link: T_LINK id ref ">" unformatted_string CT_LINK
{
	$$.sval = "\n\t\t// To create link\n" +
	"\t\tTextView link_" + $2.sval + " = new TextView(this);\n" +
	"\t\tlink_" + $2.sval + ".setText(\"" + $3.sval + "\");\n" +
	"\t\tlink_" + $2.sval + ".setId(autoID++);\n" +
	"\t\tLinkify.addLinks(link_" + $2.sval + ", Linkify.WEB_URLS );\n" +
		
	"\n\t\t// To define layout param\n" +
	"\t\tRelativeLayout.LayoutParams lpLink" + $2.sval + " = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n"+
    "\t\tlpLink" + $2.sval + ".addRule(RelativeLayout.BELOW, autoID-2);\n" +
    "\t\tlink_" + $2.sval + ".setLayoutParams(lpLink" + $2.sval + ");\n\n" +
    	
	"\t\tnudroidLayout.addView(link_" + $2.sval + ");\n\n" +
	"\t\t// Need to show link description\n"
	;
	
	listIDs.add($2.sval);
	listUrl.add($3.sval);
	listTitle.add($5.sval);
}
//| error CT_LINK {System.err.println("Malformed <link> tag.");}
;

ref: url {$$.sval = $1.sval;} 
//   | page_id {$$.sval = $1.sval;} 
   | email {$$.sval = $1.sval;}
;

page_id: P_PAGEID IDENTIFIER {$$.sval = $2.sval;}
;

//url: P_URL STRING {$$.sval = $1.sval + $2.sval;}
url: P_URL STRING {$$.sval = $2.sval;}
;

email: P_EMAIL STRING {$$.sval = $1.sval + $2.sval;}
;

/* IMAGE */
image: T_IMAGE id image_params ">" formatted_string CT_IMAGE
{
	$$.sval = "\n\t\t// To create image\n" +
		"\t\tImageView iv" + $2.sval + " = new ImageView(this);\n" +
		"\t\tURL iu" + $2.sval + " = null;\n" +
		"\t\tURLConnection co" + $2.sval + " = null;\n" +
		"\t\tInputStream is" + $2.sval + " = null;\n\n" +
		"\t\ttry {\n" +
		"\t\t\tiu" + $2.sval + " = new URL(\"" + $3.sval + "\");\n" +
		"\t\t\tco" + $2.sval + " = iu" + $2.sval + ".openConnection();\n" +
		"\t\t\tco" + $2.sval + ".connect();\n" +
		"\t\t\tis" + $2.sval + " = co" + $2.sval + ".getInputStream();\n" +
		"\t\t\tBufferedInputStream bis" + $2.sval + " = new BufferedInputStream(is" + $2.sval + ");\n" +
		"\t\t\tBitmap bm" + $2.sval + " = BitmapFactory.decodeStream(bis" + $2.sval + ");\n" +
		"\t\t\tbis" + $2.sval + ".close();\n" +
		"\t\t\tis" + $2.sval + ".close();\n" +
		"\t\t\tiv" + $2.sval + ".setImageBitmap(bm" + $2.sval + ");\n" +
		"\t\t} catch (Exception e) {\n" +
		"\t\t\te.printStackTrace();\n" +
		"\t\t}\n\n" +
		
		"\t\tiv" + $2.sval + ".setAdjustViewBounds(true);\n" +
		"\t\tiv" + $2.sval + ".setId(autoID++);\n" +
		//"\t\tiv" + $2.sval + ".setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));\n" +
		"\t\tiv" + $2.sval + ".setScaleType(ImageView.ScaleType.FIT_XY);\n" +
		
		
		"\n\t\t// To define layout param\n" +
		"\t\tRelativeLayout.LayoutParams lp" + $2.sval + " = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n"+
    	"\t\tlp" + $2.sval + ".addRule(RelativeLayout.BELOW, autoID-2);\n" +
    	"\t\tiv" + $2.sval + ".setLayoutParams(lp" + $2.sval + ");\n" +
    
    	"\n\t\tnudroidLayout.addView(iv" + $2.sval + ");\n" +
    
		"\n\t\t// Need to do more to show image description\n" +
		
		
				
		"\t\t// To create text\n" +
		"\t\tTextView tv" + $2.sval + " = new TextView(this);\n" +
		"\t\ttv" + $2.sval + ".setText(" + $5.sval + ");\n" +
		"\t\ttv" + $2.sval + ".setId(autoID++);\n" +

		"\t\t// To define layout param\n" +
		"\t\tRelativeLayout.LayoutParams lp2" + $2.sval + " = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n" +
		"\t\tlp2" + $2.sval + ".addRule(RelativeLayout.BELOW, autoID-2);\n" +
		"\t\ttv" + $2.sval + ".setLayoutParams(lp2" + $2.sval + " );\n" +

		"\t\tnudroidLayout.addView(tv" + $2.sval + ");\n" ;
		
}
   | T_IMAGE id image_params CT_SELF_CLOSING
   {
		
/*   	$$.sval = 
	"\t\t//Image2 Start;\n" +
	"\t\t\n" +
	"\t\t\n" +
	"\t\t\n" +
	"\t\t//Image2 End;\n"
	;
*/
   }
   // | error CT_IMAGE {System.err.println("Malformed <image> tag.");}
;

image_params: /* Empty String */ {$$.sval = "";}
   | image_params image_param {$$.sval = $1.sval + $2.sval;}
;

image_param: height
   | width
   | url
   | position
;

/* LIST */
list: T_LIST id list_params ">" list_items CT_LIST
{       
		$$.sval = 
		"\n\t\tListView " + $2.sval + "= new ListView(this);\n" + 
		"\t\titems.clear();\n";
         
        for(int i = 0; i < listIDs.size(); i ++)
		{
 			$$.sval = $$.sval + "\n\t\tListData " + listIDs.get(i) + "= new ListData();\n" +       
        						"\t\t" + listIDs.get(i) + ".text = " + listTitle.get(i) + ";\n" +
    							"\t\titems.add(" + listIDs.get(i) + ");\n" +
    							"\t\tlistTitleData.add(\"" + listUrl.get(i) + "\");\n";
        };       
               
        $$.sval = $$.sval +         
        		 
        "\n\t\t" + $2.sval + ".setAdapter(new IconicAdapter(this));\n" + 
		"\t\t" + $2.sval + ".setId(autoID++);\n" +
	
		"\n\t\t// To define layout param\n" +
		"\t\tRelativeLayout.LayoutParams lpList" + $2.sval + " = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n"+
	    "\t\tlpList" + $2.sval + ".addRule(RelativeLayout.BELOW, autoID-2);\n" +
	    "\t\t" + $2.sval + ".setLayoutParams(lpList" + $2.sval + ");\n\n" +
	    		
		"\t\t" + $2.sval + ".setOnItemClickListener(new OnItemClickListener()\n" +
		"\t\t{\n" +
			"\t\t\t@Override\n" +
			"\t\t\tpublic void onItemClick(AdapterView<?> parent, View v, int position, long id)\n" +
			"\t\t\t{\n" +
			
				"\t\t\t\tIntent web = new Intent(Intent.ACTION_VIEW);\n" +
				"\t\t\t\tUri u = Uri.parse(listTitleData.get(position));\n" +
				"\t\t\t\tweb.setData(u);\n" +
				"\t\t\t\tstartActivity(web);\n" +
			"\t\t\t}\n" +
		"\t\t});\n\n" +
	    
	    
	    "\t\tnudroidLayout.addView(" + $2.sval + ");\n";
}

   // | error CT_LIST {System.err.println("Malformed <list> tag.");}
;

list_params: /* Empty String */
   | list_params list_param
;

list_param: bullet
;

list_items: /* Empty String */
   | list_items list_item 
   {
   	$$.sval = $1.sval + $2.sval
   ;
   }
;

list_item: text {$$.sval = $1.sval;}
   | image
   | link {$$.sval = $1.sval;}
;

bullet: P_BULLET_STYLE STRING
;

/*bullet_type: BULLET_NUMBERS
   | BULLET_ATOZ_UPPER
   | BULLET_ATOZ_LOWER
   | BULLET_CIRCLES
   | BULLET_SQUARES
   | BULLET_DISCS
;*/

/* TABLE */
table: T_TABLE id cols ">" table_items CT_TABLE
{
	// get table name
	String table_id = $2.sval;
	// get list of table parameters
	String table_params = $3.sval;
	// get list of table items
	String table_items = $5.sval;
	
	// extract cols
	int cols = (int)($3.dval);
	
	// build XML layout contents
	LayoutBuilder LB = new LayoutBuilder();
	String table = LB.makeTable(cols);
	table += LB.addToTable("THIS",120);
	table += LB.addToTable("IS",120);
	table += LB.addToTable("A TEST",120);
	table += LB.returnTable();
	
	LB.commitLayout(table, table_id);
	
	$$.sval="";    
    tableLayout = "\t\tsetContentView(R.layout." + table_id + ");\n";	
}
// | error CT_TABLE {System.err.println("Malformed <table> tag.");}
;

//table_params: /* Empty String */
   //| table_params table_param
//{
//	$$.sval = $1.sval + $2.sval;
//}
//;

//table_param: cols
   //| label
//{
	// separating each param with a semi-colon
//	$$.sval = $1.sval + ";";
//}
//;

cols: P_COLS NUMBER
{
	$$.dval = $2.dval;
}
;

table_items: /* Empty String */
   | table_items table_item
;

table_item: text {System.out.println("Text in table");}
   | link		{System.out.println("Link in table");}
   | image		{System.out.println("Image in table");}
;


/*


text: T_TEXT id ">" formatted_string CT_TEXT
{
	$$.sval = "\n\t\t// To create text\n" +
	"\t\tfinal TextView " + $2.sval + " = new TextView(this);\n" +
	"\t\t" + $2.sval + ".setText(" + $4.sval + ");\n" +
	"\t\t" + $2.sval + ".setId(autoID++);\n" +
	

*/
/* AUDIO */
audio: T_AUDIO id audio_params ">" formatted_string CT_AUDIO
{
	String name = "mp" + $2.sval;
	$$.sval = "\t\tMediaPlayer " + name + " = new MediaPlayer();\n" +
	"\t\ttry {\n" +
    addName(name, $3.sval,3) + 
    "\t\t\t" + name + ".prepare();\n" +
    "\t\t\t" +name + ".start();\n" +
    "\t\t} catch (Exception e) {\n" +
		"\t\t\te.printStackTrace();\n" +
		"\t\t}\n\n" +
				
		"\t\t// To create text\n" +
		"\t\tTextView tv" + $2.sval + " = new TextView(this);\n" +
		"\t\ttv" + $2.sval + ".setText(" + $5.sval + ");\n" +
		"\t\ttv" + $2.sval + ".setId(autoID++);\n" +

		"\t\t// To define layout param\n" +
		"\t\tRelativeLayout.LayoutParams lp" + $2.sval + " = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n" +
		"\t\tlp" + $2.sval + ".addRule(RelativeLayout.BELOW, autoID-2);\n" +
		"\t\ttv" + $2.sval + ".setLayoutParams(lp" + $2.sval + " );\n" +

		"\t\tnudroidLayout.addView(tv" + $2.sval + ");\n" ;
    
    System.out.println("Video code:\n" + $$.sval);
}
   // | error CT_AUDIO {System.err.println("Malformed <audio> tag.");}
;

audio_params: /* Empty String */ {System.out.println("Empty audio param"); $$.sval = "";}
   | audio_params audio_param 	 {System.out.println("Recursive video param"); $$.sval = $1.sval + $2.sval;}
;

audio_param: size
   | url {System.out.println("URL"); $$.sval = ".setDataSource(\"" + $1.sval + "\");\n";}
;

/* VIDEO */
video: T_VIDEO id video_params ">" formatted_string CT_VIDEO
{
	$$.sval = "\n\t\t// To create video\n" +
	"\t\tString path = \""+ $3.sval + "\";\n" +
	"\t\tVideoView " + $2.sval + " = new VideoView(this);\n" +
	"\t\t" + $2.sval + ".setVideoPath(path);\n" +
	"\t\t" + $2.sval + ".setId(autoID++);\n" +
	
	"\t\t"  + $2.sval + ".setMediaController(new MediaController(this));\n" +
	"\t\t" + $2.sval + ".requestFocus();\n" +
	
	"\n\t\t// To define layout param\n" +
	"\t\tRelativeLayout.LayoutParams lpVideo" + $2.sval + " = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n"+
    "\t\tlpVideo" + $2.sval + ".addRule(RelativeLayout.BELOW, autoID-2);\n" +
    "\t\t" + $2.sval + ".setLayoutParams(lpVideo" + $2.sval + ");\n\n" +
    "\t\tnudroidLayout.addView(" + $2.sval + ");\n" +    
    "\t\t" + $2.sval + ".start();\n" 
	;

/*
	String name = "mp" + $2.sval;
	$$.sval = "\t\tMediaPlayer " + name + " = new MediaPlayer();\n" +
	"\t\ttry {\n" +
    addName(name, $3.sval,3) + 
    "\t\t\t" + name + ".prepare();\n" +
    "\t\t\t" +name + ".start();\n" +
    "\t\t} catch (Exception e) {\n" +
		"\t\t\te.printStackTrace();\n" +
		"\t\t}\n\n";
    
    System.out.println("Video code:\n" + $$.sval);
*/
}
   // | error CT_VIDEO {System.err.println("Malformed <video> tag.");}
;

video_params: /* Empty String */ {System.out.println("Empty video param"); $$.sval = "";}
   | video_params video_param	 {System.out.println("Recursive video param"); $$.sval = $1.sval + $2.sval;}
;

video_param: size
   | url	{System.out.println("URL"); $$.sval = $1.sval;}
;

/* BUTTON OBJECT */
button: T_BUTTON id label ">" optional_code CT_BUTTON
{ 
 $$.sval = "\n\t\t// " + $2.sval + "Button Creation\n" +
 "\t\tButton " + $2.sval + " = new Button(this);\n" +
 "\t\t" + $2.sval + ".setId(autoID++);\n" +
 "\t\t"+$2.sval+".setText(\"" + $3.sval + "\");\n" +
 
 "\t\tRelativeLayout.LayoutParams lp" + $2.sval + " = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);\n" +
 "lp" + $2.sval + ".addRule(RelativeLayout.BELOW, autoID-2);\n" +
 $2.sval + ".setLayoutParams(lp" + $2.sval + ");\n" + 
 
 "\t\tnudroidLayout.addView(" + $2.sval + ");\n" +
 "\t\t" + $2.sval + ".setOnClickListener(new View.OnClickListener() {\n" +
 "\t\t\tpublic void onClick(View v) {\n" +
 
 "\t\t\t\t" + $5.sval + "\n" +
 
 "\t\t\t}\n" +
 "\t\t});\n"
;}   
 // | error CT_BUTTON {System.err.println("Malformed <button> tag.");}
;

//function_id: P_FUNCTIONID IDENTIFIER {$$.sval = $2.sval;}
//;

/* VARIABLE */
variable: T_VAR id value CT_SELF_CLOSING
{
	System.out.println("VARIABLE tag reduced.");
	
	if(SymbolTable.containsVariable($2.sval))
	{
		System.err.println($2.sval + " has already been initialized.");
	}
	else
	{
		System.out.println("ID = " + $2.sval);
		System.out.println("Value= " + $3.sval);
		//temp = value; SymbolTable.setVar(id, temp);
		String tempVar = SymbolTable.tempVarName();
		$$.sval = "int " + tempVar + "=" + $3.sval + ";\n" +
		"SymbolTable.addVar(\"" + $2.sval + "\", " + tempVar + ");\n";
		
		SymbolTable.initializeVariable($2.sval);
		System.out.println("Initialized " + $2.sval);
		
		variableDeclarations = variableDeclarations + "\n" + $$.sval; 
	}
}
;

/*type_p: P_TYPE type
;

type: TYPE_NUMBER
   | TYPE_STRING
;*/

value: P_VALUE expression {System.out.println("Value tag = " + $2.dval); $$.sval = $2.sval; }
;

/* FUNCTION */
/*function: T_FUNCTION id ">" optional_code CT_FUNCTION
{
	$$.sval = 	"\t\tpublic void " + $2.sval + "()\n" +
				"\t\t{\n" +
				$4.sval + "\n" +
				"\t\t}\n";
}
   // | error CT_FUNCTION {System.err.println("Malformed <function> tag.");}
;*/

/* CODE */
code: action		{$$.sval = $1.sval;}
   | code action 	{$$.sval = $1.sval + "\n" + $2.sval;}
;

optional_code: /*Empty String*/ {$$.sval = "\"\"";}
   | code						{$$.sval = $1.sval;}
;

action: goto	{$$.sval = $1.sval;}
   | setvar		{$$.sval = $1.sval;}
   | getvar		{$$.sval = $1.sval;}
   | getinput	{$$.sval = $1.sval;}
   | gettext	{$$.sval = $1.sval;}
   | settext	{$$.sval = $1.sval;}
   | test		{$$.sval = $1.sval; System.out.println("Test:\n" + $1.sval);}
   | loop		{$$.sval = $1.sval;}
;

goto: T_GOTO page_id CT_SELF_CLOSING
{
	$$.sval = "\t\t startActivity(new Intent(thisPage," + $2.sval + ".class));\n";
}
;

setvar: T_SETVAR var_id value CT_SELF_CLOSING
{
	if(SymbolTable.containsVariable($2.sval))
	{
		String tempVar = SymbolTable.tempVarName();
		$$.sval = "int " + tempVar + "=" + $3.sval + ";\n" +
		"SymbolTable.setVar(\"" + $2.sval + "\", " + tempVar + ");\n";
		
		System.out.println("SetVar tag:\n" + $$.sval);
	}
	else
	{
		System.err.println($2.sval + " has not been initialized.");
	}
	
}
;

getvar: T_GETVAR var_id CT_SELF_CLOSING
{
	if(SymbolTable.containsVariable($2.sval))
	{
		//turn value into string
		$$.sval = " (\"\" + SymbolTable.getVar(\"" + $2.sval + "\"))";
	}
	else
	{
		System.err.println($2.sval + " has not been initialized.");
	}
}
;

getinput: T_GETINPUT input_id CT_SELF_CLOSING
{
	if(SymbolTable.containsInput($2.sval))
	{
		$$.sval = $2.sval + ".getText()";
	}
	else
	{
		System.err.println("Input " + $2.sval + " has not been initialized.");
	}
}
;

gettext: T_GETTEXT text_id CT_SELF_CLOSING
{
	$$.sval = $2.sval + ".getText()";
}
;

settext: T_SETTEXT text_id ">" formatted_string CT_SETTEXT
	{
		$$.sval = "\t\t" + $2.sval + ".setText(" + $4.sval + ");";
	}
   // | error CT_SETTEXT {System.err.println("Malformed <setText> tag.");}
;

//text = "value"
//text_p: P_TEXT value_text
//;

//e.g. "Result: $x"
//value_text: /* Empty String */
//   | value_text value_text_component
//;

//String literal or variable identifier
//value_text_component: UNFORMATTED_STRING
//   | IDENTIFIER
//;

/* EXPRESSIONS */
expression: expression '+' term {$$.sval = "(" + $1.sval + "+" + $3.sval + ")";}
   | expression '-' term {$$.sval = "(" + $1.sval + "-" + $3.sval + ")";}
   | term {$$.sval = $1.sval; System.out.println("term = " + $1.sval);}
;

term: term '*' factor {$$.sval = "(" + $1.sval + "*" + $3.sval + ")";}
   | term '/' factor {$$.sval = "(" + $1.sval + "/" + $3.sval + ")";}
   | factor {$$.sval = $1.sval; System.out.println("factor = " + $1.sval);}
;

factor: '(' expression ')' 	{$$.sval = "(" + $2.sval + ")";}
   | num 					{$$.sval = $1.sval; System.out.println("num = " + $1.sval);}
;

num: NUMBER {$$.sval = "" + (int)$1.dval; System.out.println("Number: " + $1.dval);}
   | getvar   
   		{
   			if(SymbolTable.containsVariable($1.sval))
   			{
   				$$.sval = "SymbolTable.getVar(\"" + $1.sval + "\")";
   			}
   			else
   			{
   				System.err.println($1.sval + " has not been initialized.");
   			}
   		}
   | getinput 
   | IDENTIFIER 
   		{
   			if(SymbolTable.containsVariable($1.sval))
   			{
   				$$.sval = "SymbolTable.getVar(\"" + $1.sval + "\")";
   			}
   			else if(SymbolTable.containsInput($1.sval))
   			{
   				
   				$$.sval = "(SymbolTable.safeParseInt(" +$1.sval + ".getText().toString()))";
   			}
   			else
   			{
   				System.err.println($1.sval + " has not been initialized or is not a variable or input.");
   			}
   		}
;

/* CONDITIONS */
condition: condition LOGIC_OR condition {$$.sval = "((" + $1.sval + ") || (" + $3.sval + "))";}
   | condition LOGIC_AND condition	{$$.sval = "((" + $1.sval + ") && (" + $3.sval + "))";}
   | '!' condition					{$$.sval = "!(" + $2.sval + ")";}
   | '(' condition ')' 				{$$.sval = "(" + $2.sval + ")";}
   | expression relop expression 	{$$.sval = "(" + $1.sval + " " + $2.sval + " " + $3.sval + ")";}
   | B_TRUE
   | B_FALSE
;

relop: "<" 		{$$.sval = "<";}
   | ">"		{$$.sval = ">";}
   | RELOP_EQ	{$$.sval = "==";}
   | RELOP_GEQ	{$$.sval = ">=";}
   | RELOP_LEQ	{$$.sval = "<=";}
   | RELOP_NEQ  {$$.sval = "!=";}
;

/* TEST */
test: T_TEST P_CONDITION condition ">" true_code false_code CT_TEST
{
	String trueCode = $5.sval;
	if(trueCode.equals("\"\""))
		trueCode = "";
		
	String falseCode = $6.sval;
	if(falseCode.equals("\"\""))
		falseCode = "";
	
	$$.sval = "if(" + $3.sval + ")\n" +
	"{\n" + trueCode + "}\n" +
	"else\n" +
	"{\n" + falseCode + "}\n";
}
   // | error CT_TEST {System.err.println("Malformed <test> tag.");}
;

true_code: T_TRUE ">" optional_code CT_TRUE {$$.sval = $3.sval;}
   // | error CT_TRUE {System.err.println("Malformed <true> tag.");}
;

false_code: T_FALSE ">" optional_code CT_FALSE {$$.sval = $3.sval;}
   // | error CT_FALSE {System.err.println("Malformed <fals> tag.");}
;

/* LOOP */
loop: T_LOOP P_START expression P_END expression ">" optional_code CT_LOOP
{
	String loop_var = SymbolTable.tempVarName();
	String boundary = SymbolTable.tempVarName();
	
	$$.sval = 	"int " + loop_var + "=" + $3.sval + ";\n" +
				"int " + boundary + "=" + $5.sval + ";\n" +
				"while(" + loop_var + " <= " + boundary + ")\n" +
				"{\n" +
				$7.sval + "\n" +
				loop_var + "++;\n" + //increment loop variable
				"}\n";
				
}
   // | error CT_LOOP {System.err.println("Malformed <loop> tag.");}
;

/* PARAMETERS */
id: P_ID IDENTIFIER {$$.sval = $2.sval ;}
;

var_id: P_VARID IDENTIFIER {$$.sval = $2.sval ;}
;

text_id: P_TEXTID IDENTIFIER {$$.sval = $2.sval ;}
;

input_id: P_INPUTID IDENTIFIER {$$.sval = $2.sval ;}
;

label: P_LABEL STRING {$$.sval = $2.sval;}
;

position: P_POSITION STRING
;

/*position_type: POSITION_TOP
   | POSITION_BOTTOM
   | POSITION_LEFT
   | POSITION_RIGHT
   | POSITION_CENTER
;*/

size: width
   | height
;

height: P_HEIGHT NUMBER
;

width: P_WIDTH NUMBER
;

//location: P_LOCATION STRING
//;

//label_orientation: P_LORIENTATION orientation_type
//;

//orientation_type: ORIENTATION_VERTICAL
//   | ORIENTATION_HORIZONTAL
//;

/* Strings */

formatted_string: /* Empty String */ {$$.sval = "\"\"";}
   | formatted_string UNFORMATTED_STRING { $$.sval = $1.sval + " + \"" + $2.sval + "\""; }
   | formatted_string link
   | formatted_string getvar {$$.sval = $1.sval + " + " + $2.sval;}
   | formatted_string getinput {$$.sval = $1.sval + " + " + $2.sval;}
   | formatted_string gettext {$$.sval = $1.sval + " + " + $2.sval;}
;

unformatted_string: /* Empty String */ {$$.sval = "\"\"";}
   | UNFORMATTED_STRING {$$.sval = "\"" + $1.sval + "\"";}
;

%%

private Yylex lexer;
private int layoutParams;
private int numMenuItems;
private static String appName;	
private String variableDeclarations;
private String navigationTemp;
private String tableLayout;
private ArrayList<String> listUrl;
private ArrayList<String> listIDs;
private ArrayList<String>listTitle;
private ArrayList<String> pageIDs;
private ArrayList<String> pageTitles;

public static void main(String args[])
{    
	
	Parser yyparser;
	
	SymbolTable.initialize();
	
	try {
		yyparser = new Parser(new FileReader(args[0]));
		yyparser.yyparse();  
	} catch (FileNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} 
}

public static StringBuilder readFile(String srcFile)
{
	StringBuilder nudroidSoucre = new StringBuilder();
	
	try
	{
		// File open
		File dirs = new File(srcFile);
		String path = dirs.getAbsolutePath();
		File realFile = new File(path);			
		FileReader fr=new FileReader(realFile);
		BufferedReader br = new BufferedReader(fr);	
	  	  
	  String str="";
  	
  	while ((str=br.readLine())!=null)
  	{
  		nudroidSoucre.append(str);
  	}
	  			
		return nudroidSoucre;
	}
	catch (Exception e)
	{
		e.getMessage();
		System.out.println("File open error: " + e);
		
		return null;
	}
}
  /* interface to the lexer */
  private int yylex () {
    int yyl_return = -1;
    try {
      yyl_return = lexer.yylex();
    }
    catch (IOException e) {
      System.err.println("IO error :"+e);
    }
    
    return yyl_return;
  }

void yyerror(String s)
{
	System.err.println("Error: "+s);
}

  /* lexer is created in the constructor */
  public Parser(Reader r) {
    lexer = new Yylex(r, this);
    layoutParams=1; //Increments to ensure unique page member names.
    numMenuItems = 0;
    navigationTemp = "";
    tableLayout = "";
    pageIDs = new ArrayList<String>();
    pageTitles = new ArrayList<String>();
    listIDs = new ArrayList<String>();
    listUrl = new ArrayList<String>();
	listTitle = new ArrayList<String>();
    //symbolTable = new HashMap<String, Type>();
    variableDeclarations = "";
  }
  
  public String addName(String name, String functions)
  {
  	return addName(name, functions, 0);
  }
  
  /* Add id name to start of parameters
  	 e.g. addName("x", ".f(y)\n.g(z)\nw.f(y)", 0) -->
  	      "x.f(y)
  	      x.g(z)
  	      w.f(y)" 
  */
public String addName(String name, String functions, int tabs)
  {
  	//System.out.println("name = " name + " functions = " + functions);
  	String output = "";
  	boolean foundDot = false;
  	boolean foundSlash = false;
  	
  	for(int i = 0; i < functions.length(); i++)
  	{
  		char nextChar = functions.charAt(i);
  		//System.out.print(nextChar + "");
  		if(nextChar == '.' && !foundDot)
  		{
  		//	System.out.print(" Found dot!\n");
  			output += name + ".";
  			foundDot = true;
  		}
  		else if(nextChar == '\\')
  		{
  		//	System.out.print(" Found slash!\n");
  			foundSlash = true;
  			output += '\\';
  		}
  		else if (nextChar == '\n')
  		{
  			//System.out.print(" Newline, reset.\n");
  			foundDot = false;
  			//foundSlash = false;
  			output += nextChar;
  			for(int j = 0; i < tabs; j++)
  				output += "\t";
  		}
  		else if ((nextChar == '\t' || nextChar == '\r'))
  		{
  		    //System.out.print(" Whitespace, keep going.\n");
  			//foundSlash = false;
  			output += nextChar;
  		}
  		else if (nextChar == ' ')
  		{
  			//System.out.print(" Found space.\n");
  			output += nextChar;
  		}
  		else
  		{
  			//System.out.print(" Non-whitespace, non-dot. No dotting here.\n");
  			foundDot = true; //Make sure not to put name before other invocations
  			output += nextChar;
  		}
  			
  	}
  	return output;
  }
  